/*  
 *  Move.cs 
 *  Copyright(c) 2007 Adam W Adair
 *
 *  This file is part of Adam's Chess Engine (ACE).
 *
 *  ACE is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *   
 *  ACE is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with ACE; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
using System;
using System.Collections.Generic;
using System.Text;

namespace ACE.Board
{
    /// <summary>
    /// Move represent a piece move.  Keeps track of the squares involved in the
    /// move and other information about the move.
    /// </summary>
    class Move
    {
        int m_from;
        int m_to;
        Piece m_promotion;
        Piece m_MovingPiece;
        Piece m_CapturePiece;

        private static int[,] m_searchHistory;

        #region Move Flags
        // move flags.  So much to keep track of.
        bool m_castle;
        bool m_en_passant_capture;
        bool m_pushing_pawn_2;
        bool m_pawn_move;
        bool m_promote;
        /// <summary>
        /// true if it is a capture move
        /// </summary>
        public bool IsCapture
        {
            get { return (m_CapturePiece != null); }
            //set { m_capture = value; }
        }

        /// <summary>
        /// true if this is a pawn promotion move.
        /// </summary>
        public bool IsPromotion
        {
            get { return m_promote; }
            set { m_promote = value; }
        }

        /// <summary>
        /// true if this is a castle move
        /// </summary>
        public bool IsCastle
        {
            get { return m_castle; }
            set { m_castle = value; }
        }

        /// <summary>
        /// true if enpassant capture
        /// </summary>
        public bool IsEnpassantCapture
        {
            get { return m_en_passant_capture; }
            set { m_en_passant_capture = value; }
        }

        /// <summary>
        /// true if is a pawn move
        /// </summary>
        public bool IsPawnMove
        {
            get { return m_pawn_move; }
            set { m_pawn_move = value; }
        }

        /// <summary>
        /// true if pushed pawn 2 spaces
        /// </summary>
        public bool IsPushingPawn2
        {
            get { return m_pushing_pawn_2; }
            set { m_pushing_pawn_2 = value; }
        }
        #endregion

        public Move()
        {
            m_CapturePiece = null;
        }

        public Move(int from, int to, Piece movingPiece)
        {
            m_from = from;
            m_to = to;
            m_MovingPiece = movingPiece;
            m_CapturePiece = null;
        }
       
        /// <summary>
        /// board offset to move piece from.
        /// </summary>
        public int From
        {
            get { return m_from; }
            set{ m_from = value; }
        }

        /// <summary>
        /// board offset to move piece to.
        /// </summary>
        public int To
        {
            get{ return m_to; }
            set{ m_to = value; }
        }

        /// <summary>
        /// Piece we are promoting to.
        /// </summary>
        public Piece PromotionPiece
        {
            get{ return m_promotion; }
            set{ m_promotion = value; }
        }

        /// <summary>
        /// The piece that is being captured;
        /// </summary>
        public Piece CapturePiece
        {
            get { return m_CapturePiece; }
            set { m_CapturePiece = value; }
        }

        /// <summary>
        /// The piece that is moving.
        /// </summary>
        public Piece MovingPiece
        {
            get{ return m_MovingPiece; }
            set { m_MovingPiece = value; }
        }

        /// <summary>
        /// A score for the move.
        /// </summary>
        public int Score
        {
            get
            {
                if (CapturePiece != null)
                {
                    return 1000000 + (CapturePiece.PieceValue * 10) - MovingPiece.PieceValue;
                }
                // we need to do this some other way later
                return 0;
            }
        }

        public string MoveString()
        {
            string retString = ChessBoard.GetCoordinate(From) + ChessBoard.GetCoordinate(To);
            return retString;
        }

        /// <summary>
        /// Compares to moves scores.
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public static int CompareMovesByScore(Move x, Move y)
        {
            if (x == null)
            {
                if (y == null)
                {
                    // If x is null and y is null, they're
                    // equal. 
                    return 0;
                }
                else
                {
                    // If x is null and y is not null, y
                    // is greater. 
                    return -1;
                }
            }
            else
            {
                // If x is not null...
                //
                if (y == null)
                // ...and y is null, x is greater.
                {
                    return 1;
                }
                else
                {
                    // return the comparison value of the two moves scores.
                    return x.Score.CompareTo(y.Score);
                }
            }

        }

        public static void ClearSearchHistory()
        {
            m_searchHistory = new int[64, 46];
        }

        public static void UpdateSearchHistory(Move move, int val)
        {
            m_searchHistory[move.From, move.To] += val;
        }

        public static int GetSearchHistoryScore(Move move)
        {
            return m_searchHistory[move.From, move.To];
        }

    }
}
